﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.IO;

namespace LevelEditor
{
    /// <summary>
    /// A structure that stores model data
    /// </summary>
    public class Mesh
    {
        /// <summary>
        /// The vertex buffer for the model
        /// </summary>
        private VertexPositionNormalTexture[] vertecies;

        /// <summary>
        /// The index buffer for the model
        /// </summary>
        private int[] indicies;

        /// <summary>
        /// The world transformation of the model
        /// </summary>
        public Matrix World = Matrix.Identity;

        /// <summary>
        /// The radius of the model
        /// </summary>
        private float radius;

        /// <summary>
        /// The bounding sphere for this model
        /// </summary>
        public BoundingSphere BSphere
        {
            get { return new BoundingSphere(new Vector3(World.M41, World.M42, World.M43), radius); }
        }

        /// <summary>
        /// Creates a new mesh with the vertecies from the specified file
        /// </summary>
        /// <param name="filename">The file to load the mesh data from</param>
        public Mesh(string filename)
        {
            using (BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open)))
            {
                uint numVerts = reader.ReadUInt32();
                // allocate vertex buffer
                vertecies = new VertexPositionNormalTexture[numVerts];
                // read vertecies
                for (int i = 0; i < numVerts; i++)
                {
                    Vector3 position = reader.ReadVector3();
                    Vector3 normal = reader.ReadVector3();
                    Vector3 tangent = reader.ReadVector3();
                    Vector2 uv = reader.ReadVector2();

                    // update the radius of the sphere
                    radius = (float)Math.Max(radius, position.Length());

                    vertecies[i] = new VertexPositionNormalTexture(position, normal, uv);
                }
                // read number of indicies
                uint numIndicies = reader.ReadUInt32();
                // allocate index buffer
                indicies = new int[numIndicies];
                // read indicies
                for (int i = 0; i < numIndicies; i++)
                    indicies[i] = (int)reader.ReadUInt32();
            }
        }

        /// <summary>
        /// Draws the model
        /// </summary>
        /// <param name="device">The device to use to draw the model</param>
        /// <param name="primitiveType">The type of primitives to use when rasterizing the model</param>
        public void Draw(GraphicsDevice device, PrimitiveType primitiveType = PrimitiveType.TriangleList)
        {
            device.DrawUserIndexedPrimitives(primitiveType, vertecies, 0, vertecies.Length, indicies, 0, indicies.Length / 3);
        }
    }
}